#include "napi/native_api.h"

namespace {
class Sample {
public:
    static napi_ref constructorRef;

    static napi_value GetInsProp(napi_env env, napi_callback_info info) {
        napi_value thisArg;
        napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr);
        napi_value result;
        napi_create_int32(env, 42, &result);
        return result;
    }

    static napi_value SetInsProp(napi_env env, napi_callback_info info) {
        napi_value result;
        return result;
    }

    static napi_value GetStaticProp(napi_env env, napi_callback_info info) {
        napi_value result;
        napi_create_int32(env, 84, &result);
        return result;
    }

    static napi_value SetStaticProp(napi_env env, napi_callback_info info) {
        napi_value result;
        return result;
    }

    static napi_value InsMethod(napi_env env, napi_callback_info info) {
        napi_value result;
        napi_create_int32(env, 126, &result);
        return result;
    }

    static napi_value StaticMethod(napi_env env, napi_callback_info info) {
        napi_value result;
        napi_create_int32(env, 252, &result);
        return result;
    }

    static napi_value Init(napi_env env, napi_value exports) {
        napi_property_descriptor properties[] = {
            {"insProp", nullptr, nullptr, GetInsProp, SetInsProp, nullptr, napi_default, nullptr},
            {"staticProp", nullptr, nullptr, GetStaticProp, SetStaticProp, nullptr, napi_static, nullptr},
            {"insMethod", nullptr, InsMethod, nullptr, nullptr, nullptr, napi_default, nullptr},
            {"staticMethod", nullptr, StaticMethod, nullptr, nullptr, nullptr, napi_static, nullptr},
        };
        napi_value cons;
        napi_status status = napi_define_class(env, "Sample", NAPI_AUTO_LENGTH, New, nullptr, sizeof(properties) / sizeof(properties[0]), properties, &cons);
        if (status != napi_ok) {
            napi_throw_error(env, nullptr, "Failed to define class");
            return exports;
        }
        napi_create_reference(env, cons, 1, &constructorRef);
        status = napi_set_named_property(env, exports, "Sample", cons);
        if (status != napi_ok) {
            napi_throw_error(env, nullptr, "Failed to set named property");
            return exports;
        }
        return exports;
    }

private:
    static napi_value New(napi_env env, napi_callback_info info) {
        napi_status status;
        napi_value instance;
        status = napi_new_instance(env, constructorRef, 0, nullptr, &instance);
        if (status != napi_ok) {
            napi_throw_error(env, nullptr, "Failed to create instance");
            return nullptr;
        }
        return instance;
    }
};
napi_ref Sample::constructorRef = nullptr;
} // namespace
